<?php
namespace xlx;
class Util
{ 
    public static function forkMethod($static_method, ...$args)
    {
        static $include;
        if (empty($include)) {
            foreach (get_declared_classes() as $composer) {
                if (substr($composer, 0, 22)=='ComposerAutoloaderInit') {
                    $ref = new \ReflectionClass($composer);
                    $file = $ref->getFileName();
                    $class = xlx\OTPWorker::class;
                    $include = "require_once '$file';$composer::getLoader();";
                }
            }
        }
        if (empty($include)) {
            throw new Exception("Error Processing Request", 1);
        }
        $string = array_reduce($args, function ($a, $b) {
            return $a.','.var_export($b, true);
        });
        $string = "$static_method(".substr($string, 1).");";
 
        if (strpos(strtolower(PHP_OS), 'win') === 0) {
            popen($c = 'start /B '.\PHP_BINARY.' -r "'.$include .' /*window select*/ '.'eval(base64_decode(\''.base64_encode($include.$string).'\'));', 'w' );
            return true;
        }
        if (function_exists('popen')) {
            popen(\PHP_BINARY.' -r "eval(base64_decode(\''.base64_encode($include.$string).'\'));" &>/dev/null ', 'w');
            return true;
        }
        if(function_exists('pcntl_fork')){
            if (pcntl_fork()==0) {
                $static_method(...$args); 
            }
            return true;
        }
        return false;
    }

    public static function checkAddr($ip, $port)
    {
        if ($port > 65536) {
            throw new \Exception("Error Port Number", 1);
        }
        if (strpos(strtolower(PHP_OS), 'win') !== 0) {//linux
            $a = @stream_socket_client("tcp://{$ip}:{$port}", $errno, $errstr, 0.00001 );
            if ($a) {
                fclose($a);
                return true;
            } else {
                return false;
            }
        }
        if (function_exists('xdebug_enable')) {//debug
            xdebug_disable();
            $a = @stream_socket_client("tcp://{$ip}:{$port}", $errno, $errstr, 0.000001);
            xdebug_enable();
            if ($a) {
                fclose($a);
                return true;
            } else {
                return false;
            }
        }
        if (strpos(strtolower(PHP_OS), 'win') === 0) {//window
            return !!\exec("netstat -ano|findstr {$ip}:{$port}");
        } else {
            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
            // ubuntu bash on windows10 not support //
            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
            return !!\exec("netstat -anp|grep {$ip}:{$port}");
        }
    }

    public static function getCoreCount()
    {
        if (isset($_SERVER['NUMBER_OF_PROCESSORS'] )) {
            return $_SERVER['NUMBER_OF_PROCESSORS'] ;//windows
        } else {
            return exec("grep 'core id' /proc/cpuinfo | sort -u | wc -l" );//linux
        }
    }
 
    public static function getEventLoop(){ 
        if(empty(\Workerman\Worker::$globalEvent)){
            \Workerman\Worker::$globalEvent = new \Events\BlockSelect(); 
        }  
        return \Workerman\Worker::$globalEvent; 
    }

    public static function getStackName($offset=0){
        $stack = \debug_backtrace();
        $stack = $stack[$offset];
        return $stack['file'].':'.$stack['line']; 
    }

    public static function encodeClosure($fn){ 
        if(!\is_callable($fn)){
            throw new Exception("Error Processing Request", 1); 
        }
        if ($fn instanceof \Closure) {
            $fn = $fn->bindTo(null, null);
            $fn = serialize(new \Opis\Closure\SerializableClosure($fn));
        } 
        return $fn;
    }
    public static function decodeClosure($any){
        if (is_string($any) && substr($any, 0, 38) =='C:32:"Opis\Closure\SerializableClosure') {
            $any = unserialize($any);
        }
        return $any;
    }
}




  
// $ip='127.0.0.1';
// $port=8109;
// \xlx\Esm::connect($ip,$port);
// \xlx\Esm::start([
//     $goto=0=>function($pid)use($goto){
//         //\xlx\Esm::send([$pid,$goto+1],'aa');   

//         for ($i=0; $i < 6; $i++) {  
//             \xlx\Esm::spawn([$pid,'then1'],function(){
//                 echo '[';
//                 sleep(6);
//                 echo ']';
//                 return 'boom|';
//             }); 
//         } 
//     }, 
//     ++$goto=>function($pid,$return)use($goto){
//         \xlx\Esm::send([$pid,$goto+1],'bb');    
//     },
//     ++$goto=>function($pid,$return)use($goto){
//         \xlx\Esm::send([$pid,$goto+1],'cc');    
//     },
//     ++$goto=>function($pid,$return)use($goto){
//         \xlx\Esm::send([$pid,$goto+1],'dd');    
//     },
//     ++$goto=>function($pid,$return)use($goto){
//         \xlx\Esm::stop([$pid]);    
//     },
//     'then1'=>function($pid,$return)use(&$arr){
//         echo $arr[]=$return;
//         if(count($arr)>=6){
//             \xlx\Esm::stop([$pid]);     
//         }
//     },
// ]); 
